Skip to content

fix: patch prototype pollution vulnerability in deepMix and mix#131

Open
Copilot wants to merge 5 commits intomasterfrom
copilot/fix-prototype-pollution-vulnerability
Open

fix: patch prototype pollution vulnerability in deepMix and mix#131
Copilot wants to merge 5 commits intomasterfrom
copilot/fix-prototype-pollution-vulnerability

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 3, 2026

  • Fix _deepMix in src/lodash/deep-mix.ts to skip dangerous keys (__proto__, constructor, prototype)
  • Add unit tests for deepMix with prototype pollution regression cases
  • Fix _mix in src/lodash/mix.ts to also skip __proto__ and prototype keys
  • Add unit tests for mix with prototype pollution regression cases
  • Bump version to 3.3.12
Original prompt

The Issue #130 in the @antv/util repository highlights a critical Prototype Pollution vulnerability in the deepMix function for versions <= 3.3.11. The deepMix function does not validate keys when merging objects, leading to potential modifications of Object.prototype properties. Attackers can exploit this to execute Denial of Service (DoS), authentication bypass, or remote code execution (RCE).

Proposed Fix:

  1. Update the deepMix function to include validation to prevent prototype pollution.
  2. Specifically, check keys such as __proto__, constructor, and prototype in the for-in loop before assignment.
  3. Add a regression test to ensure the deepMix function is resilient against object prototype pollution attacks.

Tasks:

  1. Modify the deepMix function in the file src/esm/lodash/deep-mix.js to prevent prototype modification.
  2. Write unit tests to validate the deepMix implementation with edge cases and malicious payloads from Issue Reference.
  3. Refactor and document the changes with in-place comments explaining the implementation.
  4. Update other references within the codebase to include the fixed deepMix function.
  5. Provide fixes and bash files supporting NPM validation when hit locally.

This pull request was created from Copilot chat.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI and others added 2 commits March 3, 2026 14:16
Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com>
Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix prototype pollution vulnerability in deepMix function fix: patch prototype pollution vulnerability in deepMix Mar 3, 2026
@hustcc hustcc marked this pull request as ready for review March 3, 2026 14:29
@hustcc
Copy link
Copy Markdown
Member

hustcc commented Apr 5, 2026

@copilot mix 方法是不是也有类似的问题

Copy link
Copy Markdown
Author

Copilot AI commented Apr 5, 2026

@copilot mix 方法是不是也有类似的问题

是的,mix 也有同样的问题——它只屏蔽了 constructor,但缺少对 __proto__prototype 的防护。已在 cfde1e3 修复,同时新增了回归测试。

Copilot AI changed the title fix: patch prototype pollution vulnerability in deepMix fix: patch prototype pollution vulnerability in deepMix and mix Apr 5, 2026
Copilot AI requested a review from hustcc April 5, 2026 23:54
@hustcc
Copy link
Copy Markdown
Member

hustcc commented Apr 6, 2026

@copilot 升级版本号,我准备发版本。

Agent-Logs-Url: https://github.com/antvis/util/sessions/4c19cc22-f38e-4578-b3f6-9bc3d30b8ccf

Co-authored-by: hustcc <7856674+hustcc@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Apr 6, 2026

@copilot 升级版本号,我准备发版本。

已在 965c783 将版本号从 3.3.11 升级到 3.3.12

Copilot AI requested a review from hustcc April 6, 2026 00:03
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR patches a prototype pollution vulnerability in the object-merge utilities (deepMix and mix) by skipping dangerous keys during merges, and adds regression tests to prevent reintroduction.

Changes:

  • Add __proto__ / constructor / prototype key skipping guards in src/lodash/deep-mix.ts and src/lodash/mix.ts.
  • Add new Jest unit tests covering standard merge behavior and prototype pollution vectors for both functions.
  • Update .gitignore to ignore package-lock.json.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/lodash/mix.ts Adds an early-continue guard for prototype-pollution keys during shallow merge.
src/lodash/deep-mix.ts Adds a similar guard inside the hasOwn check during deep merge recursion.
__tests__/unit/lodash/mix.spec.ts Introduces regression tests for mix merge behavior and pollution vectors.
__tests__/unit/lodash/deep-mix.spec.ts Introduces regression tests for deepMix merge behavior and pollution vectors.
.gitignore Ignores package-lock.json.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

) {
continue;
}
if (obj.hasOwnProperty(key) && obj[key] !== undefined) {
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_mix uses obj.hasOwnProperty(key), which can throw for Object.create(null) inputs and can be overridden on attacker-controlled objects. Use a safe check like Object.prototype.hasOwnProperty.call(obj, key) (or reuse the hasOwn helper pattern from deep-mix.ts) to avoid DoS and ensure the guard is reliable.

Suggested change
if (obj.hasOwnProperty(key) && obj[key] !== undefined) {
if (Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined) {

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,25 @@
import mix from '../../../src/lodash/mix';
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests import the implementation file directly. Most existing lodash unit tests import via ../../../src/lodash (public entrypoint), which better matches consumer usage and also ensures the index exports stay correct. Consider switching to import { mix } from '../../../src/lodash'.

Suggested change
import mix from '../../../src/lodash/mix';
import { mix } from '../../../src/lodash';

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +24
it('does not pollute Object.prototype via __proto__', () => {
const payload = JSON.parse('{"__proto__": {"polluted": true}}');
mix({}, payload);
expect((Object.prototype as any).polluted).toBeUndefined();
});

it('does not pollute via constructor key', () => {
const payload = JSON.parse('{"constructor": {"prototype": {"polluted": true}}}');
mix({}, payload);
expect((Object.prototype as any).polluted).toBeUndefined();
});

it('does not pollute via prototype key', () => {
mix({} as any, { prototype: { polluted: true } } as any);
expect((Object.prototype as any).polluted).toBeUndefined();
});
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prototype-pollution regression tests mutate global state if the protection ever regresses, which can cascade failures into unrelated tests. Add a beforeEach/afterEach cleanup (e.g., delete (Object.prototype as any).polluted) to keep the suite isolated and deterministic.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,30 @@
import deepMix from '../../../src/lodash/deep-mix';
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests import the implementation file directly. Most existing lodash unit tests import via ../../../src/lodash (public entrypoint), which better matches consumer usage and also ensures the index exports stay correct. Consider switching to import { deepMix } from '../../../src/lodash'.

Suggested change
import deepMix from '../../../src/lodash/deep-mix';
import { deepMix } from '../../../src/lodash';

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +29
it('does not pollute Object.prototype via __proto__', () => {
const payload = JSON.parse('{"__proto__": {"polluted": true}}');
deepMix({}, payload);
expect((Object.prototype as any).polluted).toBeUndefined();
});

it('does not pollute via constructor.prototype', () => {
const payload = JSON.parse('{"constructor": {"prototype": {"polluted": true}}}');
deepMix({}, payload);
expect((Object.prototype as any).polluted).toBeUndefined();
});

it('does not pollute via prototype key', () => {
deepMix({}, { prototype: { polluted: true } });
expect((Object.prototype as any).polluted).toBeUndefined();
});
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prototype-pollution regression tests can leave Object.prototype modified if the guard breaks, affecting later tests and making failures harder to interpret. Add cleanup in beforeEach/afterEach (e.g., delete (Object.prototype as any).polluted) to keep tests isolated.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants